<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>JavaScript异步编程和ES6+特性</title>
  <style>
    body {
      font-family: 'Arial', sans-serif;
      line-height: 1.6;
      max-width: 800px;
      margin: 0 auto;
      padding: 20px;
      color: #333;
    }
    h1 {
      color: #2c3e50;
      border-bottom: 2px solid #eee;
      padding-bottom: 10px;
    }
    .example {
      background-color: #f8f9fa;
      border-left: 4px solid #42b983;
      padding: 15px;
      margin-bottom: 20px;
      border-radius: 0 4px 4px 0;
    }
    .output {
      background-color: #f1f1f1;
      padding: 10px;
      border-radius: 4px;
      margin-top: 10px;
      font-family: monospace;
      min-height: 20px;
    }
    button {
      background-color: #42b983;
      color: white;
      border: none;
      padding: 8px 15px;
      border-radius: 4px;
      cursor: pointer;
      margin-right: 5px;
      margin-bottom: 5px;
    }
    button:hover {
      background-color: #3aa876;
    }
    .card {
      border: 1px solid #ddd;
      border-radius: 4px;
      padding: 15px;
      margin-bottom: 10px;
      background-color: white;
    }
    .loading {
      display: inline-block;
      width: 20px;
      height: 20px;
      border: 3px solid rgba(0, 0, 0, 0.1);
      border-radius: 50%;
      border-top-color: #42b983;
      animation: spin 1s ease-in-out infinite;
      margin-right: 10px;
    }
    @keyframes spin {
      to { transform: rotate(360deg); }
    }
    .error {
      color: #e74c3c;
      font-weight: bold;
    }
    .success {
      color: #42b983;
      font-weight: bold;
    }
  </style>
</head>
<body>
  <h1>JavaScript异步编程和ES6+特性</h1>
  
  <div class="example">
    <h2>回调函数</h2>
    <button onclick="demonstrateCallback()">演示回调</button>
    <button onclick="demonstrateCallbackHell()">回调地狱</button>
    <div id="callback-output" class="output"></div>
  </div>
  
  <div class="example">
    <h2>Promise</h2>
    <button onclick="demonstratePromise()">基本Promise</button>
    <button onclick="demonstratePromiseChaining()">Promise链式调用</button>
    <button onclick="demonstratePromiseAll()">Promise.all</button>
    <button onclick="demonstratePromiseRace()">Promise.race</button>
    <div id="promise-output" class="output"></div>
  </div>
  
  <div class="example">
    <h2>Async/Await</h2>
    <button onclick="demonstrateAsyncAwait()">基本Async/Await</button>
    <button onclick="demonstrateAsyncAwaitError()">错误处理</button>
    <button onclick="demonstrateParallelAsyncAwait()">并行执行</button>
    <div id="async-output" class="output"></div>
  </div>
  
  <div class="example">
    <h2>Fetch API</h2>
    <button onclick="fetchData()">获取数据</button>
    <button onclick="postData()">发送数据</button>
    <div id="fetch-output" class="output"></div>
  </div>
  
  <div class="example">
    <h2>ES6类和继承</h2>
    <button onclick="demonstrateClasses()">类和继承</button>
    <div id="class-output" class="output"></div>
  </div>
  
  <div class="example">
    <h2>解构赋值</h2>
    <button onclick="demonstrateDestructuring()">解构示例</button>
    <div id="destructuring-output" class="output"></div>
  </div>
  
  <div class="example">
    <h2>展开运算符</h2>
    <button onclick="demonstrateSpread()">展开运算符</button>
    <div id="spread-output" class="output"></div>
  </div>
  
  <div class="example">
    <h2>其他ES6+特性</h2>
    <button onclick="demonstrateArrowFunctions()">箭头函数</button>
    <button onclick="demonstrateTemplateStrings()">模板字符串</button>
    <button onclick="demonstrateOptionalChaining()">可选链</button>
    <button onclick="demonstrateNullishCoalescing()">空值合并</button>
    <div id="other-output" class="output"></div>
  </div>

  <script>
    // 辅助函数：将内容添加到输出区域
    function appendToOutput(outputId, content) {
      const output = document.getElementById(outputId);
      output.innerHTML += content + '<br>';
    }
    
    // 辅助函数：清空输出区域
    function clearOutput(outputId) {
      const output = document.getElementById(outputId);
      output.innerHTML = '';
    }
    
    // 模拟异步操作
    function simulateAsyncOperation(data, delay = 1000, shouldFail = false) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          if (shouldFail) {
            reject(new Error('操作失败'));
          } else {
            resolve(data);
          }
        }, delay);
      });
    }
    
    // 回调函数示例
    function demonstrateCallback() {
      clearOutput('callback-output');
      appendToOutput('callback-output', '开始异步操作...');
      
      // 使用回调函数处理异步操作
      setTimeout(function() {
        appendToOutput('callback-output', '第一步操作完成');
        
        // 嵌套回调
        setTimeout(function() {
          appendToOutput('callback-output', '第二步操作完成');
          appendToOutput('callback-output', '所有操作已完成');
        }, 1000);
        
      }, 1000);
    }
    
    function demonstrateCallbackHell() {
      clearOutput('callback-output');
      appendToOutput('callback-output', '开始回调地狱示例...');
      
      // 回调地狱 - 多层嵌套回调
      setTimeout(function() {
        appendToOutput('callback-output', '第一层操作完成');
        
        setTimeout(function() {
          appendToOutput('callback-output', '第二层操作完成');
          
          setTimeout(function() {
            appendToOutput('callback-output', '第三层操作完成');
            
            setTimeout(function() {
              appendToOutput('callback-output', '第四层操作完成');
              appendToOutput('callback-output', '回调地狱示例完成');
            }, 500);
            
          }, 500);
          
        }, 500);
        
      }, 500);
    }
    
    // Promise示例
    function demonstratePromise() {
      clearOutput('promise-output');
      appendToOutput('promise-output', '开始Promise示例...');
      
      // 创建一个Promise
      const myPromise = new Promise((resolve, reject) => {
        // 模拟异步操作
        setTimeout(() => {
          const success = Math.random() > 0.3; // 70%的成功率
          
          if (success) {
            resolve('操作成功完成');
          } else {
            reject(new Error('操作失败'));
          }
        }, 1000);
      });
      
      // 处理Promise
      myPromise
        .then(result => {
          appendToOutput('promise-output', `<span class="success">成功: ${result}</span>`);
        })
        .catch(error => {
          appendToOutput('promise-output', `<span class="error">错误: ${error.message}</span>`);
        })
        .finally(() => {
          appendToOutput('promise-output', 'Promise示例完成（无论成功或失败）');
        });
    }
    
    function demonstratePromiseChaining() {
      clearOutput('promise-output');
      appendToOutput('promise-output', '开始Promise链式调用示例...');
      
      // Promise链式调用
      simulateAsyncOperation('第一步数据', 1000)
        .then(result => {
          appendToOutput('promise-output', `第一步完成: ${result}`);
          return simulateAsyncOperation(`${result} -> 第二步数据`, 1000);
        })
        .then(result => {
          appendToOutput('promise-output', `第二步完成: ${result}`);
          return simulateAsyncOperation(`${result} -> 第三步数据`, 1000);
        })
        .then(result => {
          appendToOutput('promise-output', `第三步完成: ${result}`);
          appendToOutput('promise-output', '所有步骤已完成');
        })
        .catch(error => {
          appendToOutput('promise-output', `<span class="error">错误: ${error.message}</span>`);
        });
    }
    
    function demonstratePromiseAll() {
      clearOutput('promise-output');
      appendToOutput('promise-output', '开始Promise.all示例...');
      
      // 创建多个Promise
      const promise1 = simulateAsyncOperation('数据1', 1000);
      const promise2 = simulateAsyncOperation('数据2', 1500);
      const promise3 = simulateAsyncOperation('数据3', 800);
      
      // 使用Promise.all并行执行所有Promise
      Promise.all([promise1, promise2, promise3])
        .then(results => {
          appendToOutput('promise-output', '所有Promise都已完成:');
          results.forEach((result, index) => {
            appendToOutput('promise-output', `- Promise ${index + 1}: ${result}`);
          });
          appendToOutput('promise-output', `总耗时约1.5秒（最慢的Promise决定总时间）`);
        })
        .catch(error => {
          appendToOutput('promise-output', `<span class="error">至少一个Promise失败: ${error.message}</span>`);
        });
    }
    
    function demonstratePromiseRace() {
      clearOutput('promise-output');
      appendToOutput('promise-output', '开始Promise.race示例...');
      
      // 创建多个Promise，有不同的完成时间
      const promise1 = simulateAsyncOperation('快速操作', 500);
      const promise2 = simulateAsyncOperation('中速操作', 1000);
      const promise3 = simulateAsyncOperation('慢速操作', 1500);
      
      // 使用Promise.race获取最先完成的Promise结果
      Promise.race([promise1, promise2, promise3])
        .then(result => {
          appendToOutput('promise-output', `最先完成的Promise: ${result}`);
        })
        .catch(error => {
          appendToOutput('promise-output', `<span class="error">最先完成的Promise失败: ${error.message}</span>`);
        });
    }
    
    // Async/Await示例
    async function demonstrateAsyncAwait() {
      clearOutput('async-output');
      appendToOutput('async-output', '开始Async/Await示例...');
      
      try {
        // 使用await等待Promise完成
        appendToOutput('async-output', '等待第一个操作...');
        const result1 = await simulateAsyncOperation('第一步数据', 1000);
        appendToOutput('async-output', `第一步完成: ${result1}`);
        
        appendToOutput('async-output', '等待第二个操作...');
        const result2 = await simulateAsyncOperation(`${result1} -> 第二步数据`, 1000);
        appendToOutput('async-output', `第二步完成: ${result2}`);
        
        appendToOutput('async-output', '所有操作已完成');
      } catch (error) {
        appendToOutput('async-output', `<span class="error">错误: ${error.message}</span>`);
      }
    }
    
    async function demonstrateAsyncAwaitError() {
      clearOutput('async-output');
      appendToOutput('async-output', '开始Async/Await错误处理示例...');
      
      try {
        appendToOutput('async-output', '等待第一个操作...');
        const result1 = await simulateAsyncOperation('第一步数据', 1000);
        appendToOutput('async-output', `第一步完成: ${result1}`);
        
        appendToOutput('async-output', '等待第二个操作（将会失败）...');
        // 这个操作将会失败
        const result2 = await simulateAsyncOperation('第二步数据', 1000, true);
        // 这行代码不会执行，因为上面的操作会失败
        appendToOutput('async-output', `第二步完成: ${result2}`);
      } catch (error) {
        appendToOutput('async-output', `<span class="error">捕获到错误: ${error.message}</span>`);
        appendToOutput('async-output', '尽管有错误，函数仍然可以继续执行');
      }
      
      appendToOutput('async-output', '错误处理示例完成');
    }
    
    async function demonstrateParallelAsyncAwait() {
      clearOutput('async-output');
      appendToOutput('async-output', '开始并行Async/Await示例...');
      
      try {
        // 启动多个异步操作，但不等待它们
        appendToOutput('async-output', '启动所有操作...');
        const promise1 = simulateAsyncOperation('数据1', 1000);
        const promise2 = simulateAsyncOperation('数据2', 1500);
        const promise3 = simulateAsyncOperation('数据3', 800);
        
        // 并行等待所有操作完成
        const [result1, result2, result3] = await Promise.all([promise1, promise2, promise3]);
        
        appendToOutput('async-output', '所有操作已完成:');
        appendToOutput('async-output', `- 操作1: ${result1}`);
        appendToOutput('async-output', `- 操作2: ${result2}`);
        appendToOutput('async-output', `- 操作3: ${result3}`);
      } catch (error) {
        appendToOutput('async-output', `<span class="error">错误: ${error.message}</span>`);
      }
    }
    
    // Fetch API示例
    async function fetchData() {
      clearOutput('fetch-output');
      appendToOutput('fetch-output', '开始获取数据...');
      
      try {
        // 添加加载指示器
        document.getElementById('fetch-output').innerHTML += '<div class="loading"></div> 正在加载数据...';
        
        // 使用Fetch API获取数据
        const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
        
        if (!response.ok) {
          throw new Error(`HTTP错误: ${response.status}`);
        }
        
        const data = await response.json();
        
        // 清除加载指示器并显示数据
        clearOutput('fetch-output');
        appendToOutput('fetch-output', '数据获取成功:');
        appendToOutput('fetch-output', `<div class="card">`);
        appendToOutput('fetch-output', `<strong>标题:</strong> ${data.title}`);
        appendToOutput('fetch-output', `<p>${data.body}</p>`);
        appendToOutput('fetch-output', `<em>用户ID: ${data.userId}, 文章ID: ${data.id}</em>`);
        appendToOutput('fetch-output', `</div>`);
      } catch (error) {
        clearOutput('fetch-output');
        appendToOutput('fetch-output', `<span class="error">获取数据失败: ${error.message}</span>`);
      }
    }
    
    async function postData() {
      clearOutput('fetch-output');
      appendToOutput('fetch-output', '开始发送数据...');
      
      try {
        // 添加加载指示器
        document.getElementById('fetch-output').innerHTML += '<div class="loading"></div> 正在发送数据...';
        
        // 准备要发送的数据
        const newPost = {
          title: '测试文章',
          body: '这是一个通过Fetch API发送的测试文章',
          userId: 1
        };
        
        // 使用Fetch API发送POST请求
        const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify(newPost)
        });
        
        if (!response.ok) {
          throw new Error(`HTTP错误: ${response.status}`);
        }
        
        const data = await response.json();
        
        // 清除加载指示器并显示结果
        clearOutput('fetch-output');
        appendToOutput('fetch-output', '数据发送成功:');
        appendToOutput('fetch-output', `<div class="card">`);
        appendToOutput('fetch-output', `<strong>标题:</strong> ${data.title}`);
        appendToOutput('fetch-output', `<p>${data.body}</p>`);
        appendToOutput('fetch-output', `<em>用户ID: ${data.userId}, 文章ID: ${data.id}</em>`);
        appendToOutput('fetch-output', `</div>`);
      } catch (error) {
        clearOutput('fetch-output');
        appendToOutput('fetch-output', `<span class="error">发送数据失败: ${error.message}</span>`);
      }
    }
    
    // ES6类和继承示例
    function demonstrateClasses() {
      clearOutput('class-output');
      appendToOutput('class-output', '开始ES6类和继承示例...');
      
      // 定义基类
      class Person {
        constructor(name, age) {
          this.name = name;
          this.age = age;
        }
        
        greet() {
          return `你好，我是${this.name}，今年${this.age}岁。`;
        }
        
        static createAnonymous() {
          return new Person('匿名用户', 0);
        }
      }
      
      // 定义子类
      class Student extends Person {
        constructor(name, age, grade) {
          super(name, age); // 调用父类构造函数
          this.grade = grade;
        }
        
        greet() {
          return `${super.greet()} 我是${this.grade}年级的学生。`;
        }
        
        study() {
          return `${this.name}正在学习...`;
        }
      }
      
      // 使用类
      const person = new Person('张三', 30);
      appendToOutput('class-output', `Person实例: ${person.greet()}`);
      
      const student = new Student('李四', 18, '高三');
      appendToOutput('class-output', `Student实例: ${student.greet()}`);
      appendToOutput('class-output', `Student方法: ${student.study()}`);
      
      // 使用静态方法
      const anonymous = Person.createAnonymous();
      appendToOutput('class-output', `静态方法创建的实例: ${anonymous.greet()}`);
    }
    
    // 解构赋值示例
    function demonstrateDestructuring() {
      clearOutput('destructuring-output');
      appendToOutput('destructuring-output', '开始解构赋值示例...');
      
      // 数组解构
      const numbers = [1, 2, 3, 4, 5];
      const [first, second, ...rest] = numbers;
      
      appendToOutput('destructuring-output', '数组解构:');
      appendToOutput('destructuring-output', `原始数组: [${numbers}]`);
      appendToOutput('destructuring-output', `first: ${first}`);
      appendToOutput('destructuring-output', `second: ${second}`);
      appendToOutput('destructuring-output', `rest: [${rest}]`);
      
      // 对象解构
      const person = {
        name: '张三',
        age: 30,
        job: '工程师',
        address: {
          city: '北京',
          district: '海淀区'
        }
      };
      
      const { name, age, job = '未知', address: { city } } = person;
      
      appendToOutput('destructuring-output', '<br>对象解构:');
      appendToOutput('destructuring-output', `原始对象: ${JSON.stringify(person)}`);
      appendToOutput('destructuring-output', `name: ${name}`);
      appendToOutput('destructuring-output', `age: ${age}`);
      appendToOutput('destructuring-output', `job: ${job}`);
      appendToOutput('destructuring-output', `city: ${city}`);
      
      // 函数参数解构
      function printPersonInfo({ name, age, job = '未知' }) {
        return `姓名：${name}，年龄：${age}，职业：${job}`;
      }
      
      appendToOutput('destructuring-output', '<br>函数参数解构:');
      appendToOutput('destructuring-output', `函数调用结果: ${printPersonInfo(person)}`);
    }
    
    // 展开运算符示例
    function demonstrateSpread() {
      clearOutput('spread-output');
      appendToOutput('spread-output', '开始展开运算符示例...');
      
      // 数组展开
      const arr1 = [1, 2, 3];
      const arr2 = [4, 5, 6];
      
      const combined = [...arr1, ...arr2];
      appendToOutput('spread-output', '数组展开:');
      appendToOutput('spread-output', `arr1: [${arr1}]`);
      appendToOutput('spread-output', `arr2: [${arr2}]`);
      appendToOutput('spread-output', `combined: [${combined}]`);
      
      // 复制数组
      const original = [1, 2, 3];
      const copy = [...original];
      copy.push(4);
      
      appendToOutput('spread-output', '<br>复制数组:');
      appendToOutput('spread-output', `original: [${original}]`);
      appendToOutput('spread-output', `copy (修改后): [${copy}]`);
      
      // 对象展开
      const obj1 = { a: 1, b: 2 };
      const obj2 = { b: 3, c: 4 };
      
      const mergedObj = { ...obj1, ...obj2 };
      appendToOutput('spread-output', '<br>对象展开:');
      appendToOutput('spread-output', `obj1: ${JSON.stringify(obj1)}`);
      appendToOutput('spread-output', `obj2: ${JSON.stringify(obj2)}`);
      appendToOutput('spread-output', `mergedObj: ${JSON.stringify(mergedObj)}`);
      
      // 在函数调用中使用
      function sum(a, b, c) {
        return a + b + c;
      }
      
      const numbers = [1, 2, 3];
      appendToOutput('spread-output', '<br>函数参数展开:');
      appendToOutput('spread-output', `sum(1, 2, 3): ${sum(1, 2, 3)}`);
      appendToOutput('spread-output', `sum(...[1, 2, 3]): ${sum(...numbers)}`);
    }
    
    // 箭头函数示例
    function demonstrateArrowFunctions() {
      clearOutput('other-output');
      appendToOutput('other-output', '开始箭头函数示例...');
      
      // 传统函数
      function traditionalAdd(a, b) {
        return a + b;
      }
      
      // 箭头函数
      const arrowAdd = (a, b) => a + b;
      
      // 多行箭头函数
      const arrowMultiply = (a, b) => {
        const result = a * b;
        return result;
      };
      
      appendToOutput('other-output', `传统函数: traditionalAdd(5, 3) = ${traditionalAdd(5, 3)}`);
      appendToOutput('other-output', `箭头函数: arrowAdd(5, 3) = ${arrowAdd(5, 3)}`);
      appendToOutput('other-output', `多行箭头函数: arrowMultiply(5, 3) = ${arrowMultiply(5, 3)}`);
      
      // this绑定差异
      appendToOutput('other-output', '<br>this绑定差异:');
      appendToOutput('other-output', '请查看控制台输出');
      
      const person = {
        name: '张三',
        // 传统函数方法
        sayHiTraditional: function() {
          setTimeout(function() {
            console.log(`传统函数: 你好，我是${this.name}`);  // this不指向person
          }, 100);
        },
        // 箭头函数方法
        sayHiArrow: function() {
          setTimeout(() => {
            console.log(`箭头函数: 你好，我是${this.name}`);  // this指向person
          }, 100);
        }
      };
      
      person.sayHiTraditional();  // 输出：你好，我是undefined
      person.sayHiArrow();        // 输出：你好，我是张三
    }
    
    // 模板字符串示例
    function demonstrateTemplateStrings() {
      clearOutput('other-output');
      appendToOutput('other-output', '开始模板字符串示例...');
      
      const name = '张三';
      const age = 30;
      
      // 传统字符串拼接
      const traditionalGreeting = '你好，我是' + name + '，今年' + age + '岁。';
      
      // 模板字符串
      const templateGreeting = `你好，我是${name}，今年${age}岁。`;
      
      appendToOutput('other-output', '传统字符串拼接:');
      appendToOutput('other-output', traditionalGreeting);
      
      appendToOutput('other-output', '<br>模板字符串:');
      appendToOutput('other-output', templateGreeting);
      
      // 多行模板字符串
      const multilineTemplate = `这是一个
多行文本，
使用模板字符串。`;
      
      appendToOutput('other-output', '<br>多行模板字符串:');
      appendToOutput('other-output', multilineTemplate.replace(/\n/g, '<br>'));
      
      // 带表达式的模板字符串
      const a = 5;
      const b = 10;
      appendToOutput('other-output', '<br>带表达式的模板字符串:');
      appendToOutput('other-output', `${a} + ${b} = ${a + b}`);
    }
    
    // 可选链示例
    function demonstrateOptionalChaining() {
      clearOutput('other-output');
      appendToOutput('other-output', '开始可选链示例...');
      
      // 创建一个嵌套对象
      const user = {
        name: '张三',
        address: {
          city: '北京',
          street: '朝阳路'
        },
        getContact() {
          return {
            email: 'zhangsan@example.com'
          };
        }
      };
      
      // 没有可选链时的安全访问
      let cityTraditional;
      if (user && user.address && user.address.city) {
        cityTraditional = user.address.city;
      } else {
        cityTraditional = '未知';
      }
      
      // 使用可选链
      const cityOptional = user?.address?.city || '未知';
      
      appendToOutput('other-output', '传统方式访问嵌套属性:');
      appendToOutput('other-output', `城市: ${cityTraditional}`);
      
      appendToOutput('other-output', '<br>使用可选链访问嵌套属性:');
      appendToOutput('other-output', `城市: ${cityOptional}`);
      
      // 访问不存在的属性
      appendToOutput('other-output', '<br>访问不存在的属性:');
      appendToOutput('other-output', `区域: ${user?.address?.district || '未知'}`);
      
      // 方法调用与可选链
      appendToOutput('other-output', '<br>方法调用与可选链:');
      appendToOutput('other-output', `邮箱: ${user?.getContact?.()?.email || '未知'}`);
    }
    
    // 空值合并示例
    function demonstrateNullishCoalescing() {
      clearOutput('other-output');
      appendToOutput('other-output', '开始空值合并示例...');
      
      // 创建一些变量
      const a = 0;
      const b = '';
      const c = null;
      const d = undefined;
      
      // 使用逻辑或运算符 (||)
      appendToOutput('other-output', '使用逻辑或运算符 (||):');
      appendToOutput('other-output', `a || '默认值' = ${a || '默认值'}`);
      appendToOutput('other-output', `b || '默认值' = ${b || '默认值'}`);
      appendToOutput('other-output', `c || '默认值' = ${c || '默认值'}`);
      appendToOutput('other-output', `d || '默认值' = ${d || '默认值'}`);
      
      // 使用空值合并运算符 (??)
      appendToOutput('other-output', '<br>使用空值合并运算符 (??):');
      appendToOutput('other-output', `a ?? '默认值' = ${a ?? '默认值'}`);
      appendToOutput('other-output', `b ?? '默认值' = ${b ?? '默认值'}`);
      appendToOutput('other-output', `c ?? '默认值' = ${c ?? '默认值'}`);
      appendToOutput('other-output', `d ?? '默认值' = ${d ?? '默认值'}`);
      
      // 实际应用场景
      const userSettings = {
        theme: 'light',
        fontSize: 0,
        notifications: false
      };
      
      const defaultSettings = {
        theme: 'dark',
        fontSize: 16,
        notifications: true
      };
      
      // 使用逻辑或合并设置
      const mergedWithOr = {
        theme: userSettings.theme || defaultSettings.theme,
        fontSize: userSettings.fontSize || defaultSettings.fontSize,
        notifications: userSettings.notifications || defaultSettings.notifications
      };
      
      // 使用空值合并合并设置
      const mergedWithNullish = {
        theme: userSettings.theme ?? defaultSettings.theme,
        fontSize: userSettings.fontSize ?? defaultSettings.fontSize,
        notifications: userSettings.notifications ?? defaultSettings.notifications
      };
      
      appendToOutput('other-output', '<br>合并对象设置:');
      appendToOutput('other-output', `使用 || 合并: ${JSON.stringify(mergedWithOr)}`);
      appendToOutput('other-output', `使用 ?? 合并: ${JSON.stringify(mergedWithNullish)}`);
    }